package org.jeecg.modules.iot.middleware.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.jeecg.jt808.req.LocationNewMsg;
import org.jeecg.modules.iot.model.FieldStatus;
import org.jeecg.modules.iot.model.Location;
import org.jeecg.modules.iot.model.MqttMessageJson;
import org.jeecg.modules.iot.model.SocketPort;
import org.jeecg.modules.iot.model.Track.Calories;
import org.jeecg.modules.iot.model.Track.Tracking;
import org.jeecg.modules.iot.model.cabinet.CabinetHeartbeatData;
import org.jeecg.modules.iot.model.cabinet.CabinetOpenDoorData;
import org.jeecg.modules.iot.model.cabinet.CabinetRegisterData;
import org.jeecg.modules.iot.model.cabinet.CabinetSwapData;
import org.jeecg.modules.iot.model.power.TaiPower;
import org.jeecg.modules.iot.model.socket.*;
import org.jeecg.modules.rental.entity.RentalEBike;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import static org.jeecg.modules.iot.util.MD5.generateSignature;


public class JsonUtil {
    private static final Pattern JSON_PATTERN = Pattern.compile(
            "^\\s*(\\{.*}|\\[.*])\\s*$"
    );
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public static boolean hasFields(String jsonString, String... fieldNames) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(jsonString);

            for (String fieldName : fieldNames) {
                if (!jsonNode.has(fieldName)) {
                    return false;
                }
            }

            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean isJson(String jsonString) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(jsonString);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    public static Object parseJsonData(String json) throws Exception {
        // 解析 JSON 字符串
        JsonNode rootNode = objectMapper.readTree(json);
        int cmd = rootNode.get("CMD").asInt();

        // 根据 CMD 的值返回不同的实体类对象
        switch (cmd) {
            case 0:
                return objectMapper.treeToValue(rootNode, DeviceLoginData.class);
            case 1:
                return objectMapper.treeToValue(rootNode, DeviceHeartbeatData.class);
            case 2:
                return objectMapper.treeToValue(rootNode, DeviceReportData.class);
            case 3:
                return objectMapper.treeToValue(rootNode, CloseAndOpenResponse.class);
            case 4:
                return objectMapper.treeToValue(rootNode, CloseAndOpenResponse.class);
            case 5:
            case 6:
            case 10:
                return objectMapper.treeToValue(rootNode, OtherCMDData.class);
            default:
                throw new IllegalArgumentException("未识别的 CMD 值: " + cmd);
        }
    }
    public static Object parseCabinetJsonData(String json) throws Exception {
        // 解析 JSON 字符串
        JsonNode rootNode = objectMapper.readTree(json);
        String code = rootNode.get("code").asText();
        JsonNode bodyNode = rootNode.get("body");

        // 根据 code 的值返回不同的实体类对象
        switch (code) {
            case "register":
                return objectMapper.treeToValue(bodyNode, CabinetRegisterData.class);
            case "heartbeat":
                return objectMapper.treeToValue(bodyNode, CabinetHeartbeatData.class);
            case "swap":
                return objectMapper.treeToValue(bodyNode, CabinetSwapData.class);
            case "openDoor":
                return objectMapper.treeToValue(bodyNode, CabinetOpenDoorData.class);
            default:
                throw new IllegalArgumentException("未识别的 code 值: " + code);
        }
    }
    public static String createResponseJson(Object data) throws Exception {
       if (data instanceof DeviceReportData) {
            DeviceReportData reportData = (DeviceReportData) data;
            DeviceReportResponse response = new DeviceReportResponse();
            response.setDeviceCode(reportData.getDeviceCode());
            response.setCmd(reportData.getCmd());
            response.setSeq(reportData.getSeq());
            return objectMapper.writeValueAsString(response);
        }
        throw new IllegalArgumentException("未识别的数据类型: " + data.getClass().getName());
    }

    public static boolean is808Json(String jsonString) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(jsonString);
            boolean hasIdAndCmd = hasFields(jsonString, "id", "cmd");
            if (!hasIdAndCmd){
                return false;
            }
            boolean hasIdAndData = hasFields(jsonString, "id", "data");
            if (!hasIdAndData){
                return  false;
            }

            boolean hasIdAndSeq = hasFields(jsonString, "id", "seq");
            if (!hasIdAndSeq){
                return  false;
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    public static boolean isChargePileJson(String json) {
        try {
            JsonNode rootNode = objectMapper.readTree(json);
            // 检查必要字段
            if (rootNode.has("DEVICE") && rootNode.has("CMD")) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public static boolean isCabinetJson(String jsonString) {
        try {
            JsonNode jsonNode = objectMapper.readTree(jsonString);

            // 检查是否包含 "type" 和 "code" 字段
            if (!jsonNode.has("type") || !jsonNode.has("code")) {
                return false;
            }

            // 检查 "type" 字段的值是否为 "cmd"
            if (!"cmd".equals(jsonNode.get("type").asText())) {
                return false;
            }

            // 检查 "code" 字段的值是否为 "register", "heartbeat", "swap", "openDoor"
            String code = jsonNode.get("code").asText();
            return "register".equals(code) || "heartbeat".equals(code) || "swap".equals(code) || "openDoor".equals(code);
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean isClientConnectJson(String jsonString) {
        try {
            JsonNode jsonNode = objectMapper.readTree(jsonString);

            // 检查是否包含 "username", "event", 和 "clientid" 字段
            if (!jsonNode.has("username") || !jsonNode.has("event") || !jsonNode.has("clientid")) {
                return false;
            }

            // 检查 "username" 和 "clientid" 字段是否为字符串类型
            if (!jsonNode.get("username").isTextual() || !jsonNode.get("clientid").isTextual()) {
                return false;
            }

            // 检查 "clientid" 是否为纯数字
            String clientId = jsonNode.get("clientid").asText();
            if (!clientId.matches("\\d+")) { // 使用正则表达式匹配纯数字
                return false;
            }

            return true;
        } catch (Exception e) {
            return false;
        }
    }



    public static String createPubJson(Integer code, boolean status, Object data) {
        // 创建外部 JSON 数据的 Map
        Map<String, Object> outerJsonMap = new HashMap<>();
        outerJsonMap.put("code", code);
        outerJsonMap.put("status", status);

        // 使用 ObjectMapper 将 data 对象转换为 JSON 节点
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode dataNode = null;

        if (data instanceof Location) {
            Location location = (Location) data;
            ObjectNode locationNode = objectMapper.createObjectNode();
            locationNode.put("lat", location.getLatitude());
            locationNode.put("lon", location.getLongitude());
            locationNode.put("ele", location.getElevation());
            locationNode.put("spd", location.getSpeed()*0.1);
            locationNode.put("dir", location.getDirection());
            locationNode.put("mil", formatMileage(location.getMileage()));//历史里程
            locationNode.put("smil", formatMileage(location.getSMileage()));//单次里程
            locationNode.put("sCon", formatMileage(location.getSConsum()));//当前功耗
            locationNode.put("eCon", formatMileage(location.getEConsum()));//平均功耗
            locationNode.put("status", location.getOnlineStatus());//平均功耗
            dataNode = locationNode;
        } else if (data instanceof SocketPort) {
            SocketPort socketPort = (SocketPort) data;
            ObjectNode socketPortNode = objectMapper.createObjectNode();
            socketPortNode.put("port", socketPort.getPortId());
            socketPortNode.put("stat", socketPort.getBtStat());
            socketPortNode.put("oTime", socketPort.getOutTime());
            socketPortNode.put("energy", socketPort.getEnergy());
            socketPortNode.put("deviceCode", socketPort.getDeviceCode());
            socketPortNode.put("power", socketPort.getPower());
            dataNode = socketPortNode;
        }else if (data instanceof TaiPower) {
            TaiPower taiPower = (TaiPower) data;
            ObjectNode socketPortNode = objectMapper.createObjectNode();
            socketPortNode.put("rPowCap", taiPower.getRPowCap());
            socketPortNode.put("rPow", taiPower.getRPow());
            socketPortNode.put("vol", taiPower.getVoltage());
            socketPortNode.put("cur",taiPower.getCurrent());
            dataNode = socketPortNode;
        }else if (data instanceof Tracking) {
            Tracking tracking = (Tracking) data;
            ObjectNode socketPortNode = objectMapper.createObjectNode();
            socketPortNode.put("rMileage", tracking.getRMileage());
            dataNode = socketPortNode;
        }else if (data instanceof FieldStatus) {
            FieldStatus fieldStatus = (FieldStatus) data;
            ObjectNode socketPortNode = objectMapper.createObjectNode();
            socketPortNode.put("acc", fieldStatus.isAcc());
            socketPortNode.put("doorLocked", fieldStatus.isDoorLocked());
            socketPortNode.put("sportMode", fieldStatus.isSportMode());

            dataNode = socketPortNode;
        } else if (data instanceof LocationNewMsg) {
            LocationNewMsg locationNewMsg = (LocationNewMsg) data;
            ObjectNode locationNewMsgNode = objectMapper.createObjectNode();
            ObjectNode socketPortNode = objectMapper.createObjectNode();

            // 检查 SOC 是否为 null，并提供默认值
            Integer soc = locationNewMsg.getSoc();
            socketPortNode.put("rPowCap", soc != null ? soc : 0);

            // 检查剩余容量和电压是否为 null
            Integer remainingCapacity = locationNewMsg.getRemainingCapacity();
            Integer batteryVoltage = locationNewMsg.getBatteryVoltage();

            // 计算 rPow，确保不为空并进行默认值处理
            double rPow = (remainingCapacity != null ? remainingCapacity : 0) *
                    (batteryVoltage != null ? batteryVoltage : 0) * 0.001;
            socketPortNode.put("rPow", rPow);

            // 检查电压，单位转换
            socketPortNode.put("vol", batteryVoltage != null ? batteryVoltage * 0.1 : 0);

            // 检查电流，单位转换
            Integer batteryCurrent = locationNewMsg.getBatteryCurrent();
            socketPortNode.put("cur", batteryCurrent != null ? batteryCurrent * 0.0001 : 0);

            dataNode = socketPortNode;
        }else if (data instanceof Calories){
            Calories calories = (Calories) data;
            ObjectNode socketPortNode = objectMapper.createObjectNode();
            socketPortNode.put("calories", calories.getCalorise());
            dataNode = socketPortNode;
        }


        else {
            // 将其他类型的数据转换为 JSON 节点
            dataNode = null;
        }

        outerJsonMap.put("data", dataNode);

        String outerJsonString = "";
        try {
            outerJsonString = objectMapper.writeValueAsString(outerJsonMap);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return outerJsonString;
    }
    public static String createPubLocation(Location location) {
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode locationNode = objectMapper.createObjectNode();
        // 使用简短的字段名
        locationNode.put("lat", location.getLatitude());
        locationNode.put("lon", location.getLongitude());
        locationNode.put("ele", location.getElevation());
        locationNode.put("spd", location.getSpeed());
        locationNode.put("dir", location.getDirection());

        String jsonString = "";
        try {
            jsonString = objectMapper.writeValueAsString(locationNode);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return jsonString;
    } public static String createPubSocket(SocketPort socketPort) {
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode socketNode = objectMapper.createObjectNode();
        // 使用简短的字段名
        socketNode.put("port", socketPort.getPortId());
        socketNode.put("stat", socketPort.getBtStat());
        socketNode.put("oTime", socketPort.getOutTime());
        socketNode.put("energy", socketPort.getEnergy());
        socketNode.put("deviceCode", socketPort.getDeviceCode());
        socketNode.put("power", socketPort.getPower());

        String jsonString = "";
        try {
            jsonString = objectMapper.writeValueAsString(socketNode);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return jsonString;
    }

    public static String createMqttMessageJson(String data, RentalEBike rentalCar, String cmd, String seq ) throws  JsonProcessingException {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMddHHmmss");
        String currentTime =now.format(formatter);
        ObjectMapper objectMapper=new ObjectMapper();
        MqttMessageJson mqttMessageJson = new MqttMessageJson();
        mqttMessageJson.setId(rentalCar.getCarCode());
        mqttMessageJson.setEnrc(0);
        mqttMessageJson.setVender(1);
        mqttMessageJson.setCmd(cmd);
        mqttMessageJson.setTimestamp(currentTime);
        mqttMessageJson.setSeq( seq );
        mqttMessageJson.setData(data);
        String sign=generateSignature(mqttMessageJson.getId(),mqttMessageJson.getEnrc(),mqttMessageJson.getVender(),mqttMessageJson.getCmd(),mqttMessageJson.getTimestamp(),mqttMessageJson.getSeq(),mqttMessageJson.getData());
        mqttMessageJson.setSign(sign);
        return objectMapper.writeValueAsString(mqttMessageJson);
    }
    public static String formatSeq(String seq) {
        if (seq.length() < 4) {
            return String.format("%04d", Integer.parseInt(seq));
        } else {
            return seq;
        }
    }

    public static float formatMileage(Float mileage) {
        if (mileage == null) {
            return 0f;
        }

        BigDecimal mileageBigDecimal = new BigDecimal(mileage).setScale(2, RoundingMode.HALF_UP);
        return mileageBigDecimal.floatValue();
    }
}
